package com.hxh.generater.springBoot.util.methodParse;

import com.hxh.generater.springBoot.util.methodParse.entity.MethodBase;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 解析mybatis方法文件
 */
public class ParseMybatisXmlMethod {

    private static String methodTag = null;
    private static List<MethodBase> methodList = new ArrayList<>();
    private static MethodBase currentMethod;

    private static final List<String> methodTagList = new ArrayList<>();

    static {
        methodTagList.add("insert");
        methodTagList.add("select");
        methodTagList.add("update");
        methodTagList.add("delete");
    }

    private static String getCurrentMethodTag(String line, String startOrEnd) {
        line = line.trim();
        String tag = "<";
        if ("end".equals(startOrEnd)) {
            tag = "</";
        }
        for (String s : methodTagList) {
            if (line.toLowerCase().startsWith(tag + s)) {
                return s;
            }
        }
        return null;
    }

    private static void processMethod(String line, int currentLine) {
        if (StringUtils.isNotBlank(line)) {
            if (methodTag == null && line.contains("id") && line.contains("<") && line.contains(">")) {
                String lineTrim = line.trim();
                lineTrim = lineTrim.replaceAll("\\s+", " ");

                methodTag = getCurrentMethodTag(lineTrim,"start");
                if (StringUtils.isBlank(methodTag)) {
                    return;
                }

                String methodName = lineTrim.substring(lineTrim.indexOf("id=")+4);
                methodName = methodName.replaceAll("'", "\"");
                methodName = methodName.substring(0, methodName.indexOf("\""));

                if (currentMethod == null) {
                    currentMethod = new MethodBase();
                }
                currentMethod.setMethodName(methodName);
                currentMethod.setStartLine(currentLine);
                currentMethod.setMethodContent(line);
            } else if (methodTag != null) {
                currentMethod.setMethodContent(currentMethod.getMethodContent() + "\n" + line);
                String endTag = getCurrentMethodTag(line,"end");
                if (StringUtils.isNotBlank(endTag) && endTag.equals(methodTag)) {
                    methodTag = null;
                }
            }
        }

        if (methodTag == null && currentMethod != null) {
            currentMethod.setEndLine(currentLine);
            methodList.add(currentMethod);
            currentMethod = null;
        }
    }

    public static List<MethodBase> parser(String path) throws IOException {
        return parser(new File(path));
    }

    public static List<MethodBase> parser(File template) throws IOException {
        methodTag = null;
        methodList = new ArrayList<>();
        currentMethod = null;

        if (!template.exists()) {
            return methodList;
        }
        BufferedReader br = new BufferedReader(new FileReader(template));
        String line;

        int currentLine = 1;
        while ((line = br.readLine()) != null) {
            processMethod(line, currentLine);
            currentLine++;
        }
        br.close();
        return methodList;
    }

    /**
     * 传入一个类的所有方法，把重复的方法打上标签
     * 在文件中从上往下扫描，最后一个重复的方法不打标签
     *
     * @param list 需要扫描的方法集合
     * @return 返回所有重复的方法，就是需要抛弃的方法
     */
    public static List<MethodBase> tagRepeatMethod(List<MethodBase> list) {
        List<MethodBase> resultList = new ArrayList<>();
        if (CollectionUtils.isEmpty(list)) {
            return resultList;
        }
        List<Integer> hashCodeList = new ArrayList<>();
        Map<Integer, List<MethodBase>> listHashMap = new HashMap<>();

        for (MethodBase javaClassMethod : list) {
            int hashCode = javaClassMethod.hashCode();
            if (hashCodeList.contains(hashCode)) {
                //旧的method，全部打上重复的标签
                List<MethodBase> list1 = listHashMap.get(hashCode);
                list1.forEach(st -> st.setRepeat(true));
                //新的method，没有打上便签
                list1.add(javaClassMethod);
                listHashMap.put(hashCode, list1);
            } else {
                List<MethodBase> list1 = new ArrayList<>();
                list1.add(javaClassMethod);
                listHashMap.put(hashCode, list1);
                hashCodeList.add(hashCode);
            }
        }
        for (MethodBase javaClassMethod : list) {
            if (javaClassMethod.isRepeat()) {
                resultList.add(javaClassMethod);
            }
        }
        return resultList;
    }
}
